// Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
// This source file is part of the Cangjie project, licensed under Apache-2.0
// with Runtime Library Exception.
//
// See https://cangjie-lang.cn/pages/LICENSE for license information.

/**
 * @file
 *
 * This file declares the cjnative backend class.
 */

#ifndef CANGJIE_DRIVER_BACKEND_CJNATIVE_H
#define CANGJIE_DRIVER_BACKEND_CJNATIVE_H

#include "cangjie/Driver/Backend/Backend.h"
#include "cangjie/Driver/DriverOptions.h"
#include "cangjie/Option/Option.h"

namespace Cangjie {
/**
 * CJNATIVEBackend generates three different kind of tools representing three different compiling stages.
 * The first stage is 'opt', which does some preprocessing on bitcode and outputs intermediate bitcode files.
 * The second stage is 'llc', which compiles bitcode into object files.
 * The final stage is 'ld', which links object files together and outputs an executable or a dynamic library.
 * For each input bitcode file, an 'opt' and a 'llc' tool will be generated.
 * Only one 'ld' linker will be used to create an executable file from all the object files (including those
 * given as input).
 */
class CJNATIVEBackend : public Backend {
public:
    /**
     * @brief The constructor of class CJNATIVEBackend.
     *
     * @param job The compilation job.
     * @param driverOptions The data structure is obtained through parsing the compilation options.
     * @param driver It is the object that triggers the compiler's compilation process.
     * @return CJNATIVEBackend The instance of CJNATIVEBackend.
     */
    CJNATIVEBackend(Job& job, const DriverOptions& driverOptions, const Driver& driver)
        : Backend(job, driverOptions, driver){};

    /**
     * @brief The destructor of class CJNATIVEBackend.
     */
    ~CJNATIVEBackend() = default;

protected:
    bool GenerateToolChain() override;
    /**
     * @brief Scan where 'opt', 'llc' and 'ld' are and get their paths.
     */
    bool PrepareDependencyPath() override;

    bool ProcessGeneration() override;

private:
    static const std::string tempFolder;

    std::string optPath;
    std::string llcPath;

    /**
     * @brief Create an instance of a cjnative base tool.
     */
    std::unique_ptr<Tool> GenerateCJNativeBaseTool(const std::string& toolPath);

    std::vector<TempFileInfo> GetFrontendOutputs();

    void GenerateCacheCopyTool(const std::vector<TempFileInfo>& files, const std::string& extension);

    /**
     * @brief This function generates 'opt' tools. For each .bc input file, an 'opt' tool is generated.
     * The output is a list of filenames, which are output files of 'opt' tools.
     * We name it PreprocessTool here because the cjnative backend not only does optimize (what 'opt' stands for),
     * but also does some important bitcode transformation (e.g. intrinsic functions) that 'llc' requires.
     */
    std::vector<TempFileInfo> GeneratePreprocessTools(const std::vector<TempFileInfo>& bitCodeFiles);

    void PreprocessOfNewPassManager(Tool& tool);
    bool ProcessGenerationOfNormalCompile(const std::vector<TempFileInfo>& bitCodeFiles);
    bool ProcessGenerationOfIncrementalNoChangeCompile(const std::vector<TempFileInfo>& bitCodeFiles);

    /**
     * @brief This function generates 'llc' tools. For each .opt.bc input file (which is output file from 'opt' tools)
     * a 'llc' tool is generated. The return is a list of files generated by 'llc' tools.
     */
    std::vector<TempFileInfo> GenerateCompileTool(
        const std::vector<TempFileInfo>& bitCodeFiles, bool emitAssembly = false);
};
} // namespace Cangjie

#endif // CANGJIE_DRIVER_BACKEND_CJNATIVE_H
